
#include "TAIC.h"

int main(int argc, const char* argv[])
{
	int nRetCode = 0;
	CMyRandom::InitRandomSeed();
	CImageEx::Initialize();

	if (1)
	{
		string strFN_Configuration		=	argv[1];
		string strOperation				=	argv[2];

		strOperation += "00000000";

		int op_TrainNBM				= CDataStructureTools::Hex2Num(strOperation[0]);
		int op_ClassificationTask	= CDataStructureTools::Hex2Num(strOperation[1]);

		char strTemp[10001] = "";

		//////////	Config Loading	//////////

		CConfiguration Config(strFN_Configuration);
		Config.Load();

		string strFN_OutLog =
			Config.GetString("strFN_OutLog", "Global.log");
		string strFN_ShortLog =
			Config.GetString("strFN_ShortLog", "Short.log");

		sprintf_s(strTemp, "del %s", strFN_OutLog.c_str());
		CExternalTools::ConsoleTools::RunDosCommand("", strTemp);
		sprintf_s(strTemp, "del %s", strFN_ShortLog.c_str());
		CExternalTools::ConsoleTools::RunDosCommand("", strTemp);

		ofstream outFile_GlobalLog(strFN_OutLog.c_str());
		CExternalTools::ConsoleTools::MakeCurrentLine("", true);
		CExternalTools::ConsoleTools::OutputTextToStream(outFile_GlobalLog, "", true);
		ofstream outFile_ShortLog(strFN_ShortLog.c_str());

		EnvVar.strFN_ClassLabel =
			Config.GetString("strFN_ClassLabel");
		EnvVar.strPN_ModelBase =
			Config.GetString("strPN_ModelBase");
		EnvVar.strFN_Task =
			Config.GetString("strFN_Task");

		int DefaultK =
			Config.GetInt("DefaultK");
		int DefaultW =
			Config.GetInt("DefaultW");
		double DefaultThresholdPWC =
			Config.GetDouble("DefaultThresholdPWC", 0.0);
		double DefaultLambda =
			Config.GetDouble("DefaultLambda");

		int MaxExampleAmount_Train = 
			Config.GetInt("MaxExampleAmount_Train");
		int MaxExampleAmount_Test = 
			Config.GetInt("MaxExampleAmount_Test");

		int RepeatAmount_NB =
			Config.GetInt("RepeatAmount_NB");
		int RepeatAmount_SVM =
			Config.GetInt("RepeatAmount_SVM");

		CClassDataSet& FullDataSet = EnvVar.FullDataSet;
		FullDataSet.myInit(EnvVar.strFN_ClassLabel);

		if (1)
		{
			int n_image = 800;
			int nx = 32;
			int ny = 25;
			int W = 23;
			int H = 23;
			int dx = 2;
			int dy = 2;
			string strPN_CodeDirShow = "D:\\HiBoost\\Dataset\\SIFT.dict.cyq\\show\\";

			int i_image;
			CImg<int> imgOutput;
			CImg<int> imgSrc;
			CImg<int> imgEnlarged;

			imgOutput.assign(dx+(W+dx)*nx,dy+(H+dy)*ny,1,3);
			imgOutput.fill(128);
			for ( i_image = 0; i_image < n_image; ++i_image )
			{
				int ix = i_image%nx*(W+dx)+dx;
				int iy = i_image/nx*(H+dy)+dy;
				sprintf_s(strTemp, "%s%d.jpg", strPN_CodeDirShow.c_str(), i_image);
				CExternalTools::myLoadImage(strTemp, imgSrc);
				imgEnlarged = imgSrc.resize(W, H, -100, 6);
				imgOutput.draw_image(imgEnlarged, ix, iy);
			}
			sprintf_s(strTemp, "%s..\\SIFT.dictionary.jpg", strPN_CodeDirShow.c_str());
			CExternalTools::mySaveImage(strTemp, imgOutput);
		}

		// ********** Main Code Start **********
		if (0)
		{
			if (op_TrainNBM & 1)
			{
				CExternalTools::ConsoleTools::MakeDirectory(EnvVar.strPN_ModelBase, true);

				int i_Class;
				CSingleClassNaiveBayesModel_TAIC tNBM, rNBM;
				double tt;
				double aMD, cMD, tbMD, thMD;
				double aED, cED, tbED, thED;
				double aCS, cCS, tbCS, thCS;
				double aKL, cKL, tbKL, thKL;
				CWeightedClassificationExampleList tFullImageExampleList;
				int K, W;
				int bK, bW;
				double bThPWC;
				int rK, rW;

				bK = DefaultK; bW = DefaultW; bThPWC = DefaultThresholdPWC;

				CSimpleStatistics stK, stW;
				stK.Clear(); stW.Clear();

				sprintf_s(strTemp, "CID\tA.MD\tC.MD\tTb.MD\tTh.MD\tA.ED\tC.ED\tTb.ED\tTh.ED\tA.CS\tC.CS\tTb.CS\tTh.CS\tA.KL\tC.KL\tTb.KL\tTh.KL\trW\tbW\tCName");
				CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, true);
				for ( i_Class = 0; i_Class < FullDataSet.ClassAmount; ++i_Class )
				{
					const CClassInformation& tClassInfo = FullDataSet.List_ClassInfo.pElement[i_Class];
					const CSourceFeatureCountDataSet* pSrcFCDS = FullDataSet.GetPtrFCDS(i_Class);

					tNBM.Clear();
					pSrcFCDS->MakeSingleClassImageExampleList(tClassInfo.In_FCDS_Label, tFullImageExampleList, true, -1, -1, 0);
					tNBM.InitImageModel(pSrcFCDS, tClassInfo.In_FCDS_Label, tFullImageExampleList, -1, -1, 0);

					tNBM.vecF_P_f_given_c_D.Fill(1.0 / tNBM.FeatureDimension);
					aMD = CVectorMath::ManhattanDistance(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);
					aED = CVectorMath::EulerDistance(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);
					aCS = CVectorMath::CosineSimilarity(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);
					aKL = CVectorMath::KL_Divergence(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);

					rK = -1; rW = -1;
					cMD = cED = cCS = cKL = -1.0;
					tbMD = tbED = tbCS = tbKL = -1.0;
					thMD = thED = thCS = thKL = -1.0;

					tNBM.InitTextModel(pSrcFCDS, tClassInfo.In_FCDS_Label, bK, 0, bThPWC);
					bW = tNBM.WordDimension;
					tbMD = CVectorMath::ManhattanDistance(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);
					tbED = CVectorMath::EulerDistance(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);
					tbCS = CVectorMath::CosineSimilarity(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);
					tbKL = CVectorMath::KL_Divergence(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);

					K = bK;
					//for ( K = 5; K <= 50; K += 5 )
					{
						for ( W = 1; W <= 10; ++W )
						{
							tNBM.InitTextModel(pSrcFCDS, tClassInfo.In_FCDS_Label, K, W, 0.0);

							tt = CVectorMath::ManhattanDistance(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);
							if ((cMD<0 || cMD>tt) && (W==1)) cMD = tt;
							//if ((tbMD<0 || tbMD>tt) && (K==bK && W==bW)) tbMD = tt;
							if ((thMD<0 || thMD>tt)) thMD = tt;

							tt = CVectorMath::EulerDistance(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);
							if ((cED<0 || cED>tt) && (W==1)) cED = tt;
							//if ((tbED<0 || tbED>tt) && (K==bK && W==bW)) tbED = tt;
							if ((thED<0 || thED>tt)) thED = tt;

							tt = CVectorMath::CosineSimilarity(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);
							if ((cCS<0 || cCS<tt) && (W==1)) cCS = tt;
							//if ((tbCS<0 || tbCS<tt) && (K==bK && W==bW)) tbCS = tt;
							if ((thCS<0 || thCS<tt)) thCS = tt;

							tt = CVectorMath::KL_Divergence(tNBM.vecF_P_f_given_c_V, tNBM.vecF_P_f_given_c_D);
							if ((cKL<0 || cKL>tt) && (W==1)) cKL = tt;
							//if ((tbKL<0 || tbKL>tt) && (K==bK && W==bW)) tbKL = tt;
							if ((thKL<0 || thKL>tt))
							{
								thKL = tt;
								rNBM = tNBM;
								rK = K; rW = W;
							}
						}
					}

					stK.NewInstance(rK); stW.NewInstance(rW);

					rNBM.InitLambda(DefaultLambda);
					rNBM.SaveToFile(EnvVar.GetFN_Model(i_Class));

					sprintf_s(strTemp, "%03d\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%.3lf\t%d\t%d\t%s",
						i_Class,
						aMD, cMD, tbMD, thMD,
						aED, cED, tbED, thED,
						aCS, cCS, tbCS, thCS,
						aKL, cKL, tbKL, thKL,
						rW, bW, tClassInfo.strName.c_str());
					
					CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, true);
					sprintf_s(strTemp, "Trained Naive Bayes Model [%03d/%d %s]...",
						i_Class, FullDataSet.ClassAmount, tClassInfo.strName.c_str());
					CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, false);
				}

				double Kx, Ky, Wx, Wy;
				stK.Analyse(Kx, Ky);
				stW.Analyse(Wx, Wy);

				sprintf_s(strTemp, "Finished Training Naive Bayes Model [%d], Avg.K [%.2lf], Avg.W [%.2lf];\n",
					FullDataSet.ClassAmount, Kx, Wx);
				CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, true);
				CExternalTools::ConsoleTools::OutputTextToStream(outFile_GlobalLog, strTemp, true);
			} // (op_TrainNBM & 1)

			if (op_TrainNBM & 2)
			{
				CExternalTools::ConsoleTools::MakeDirectory(EnvVar.strPN_ModelBase, true);

				int i_Class;
				CSingleClassNaiveBayesModel_TAIC tNBM, rNBM;
				double tt;
				double vMD;
				double vED;
				double vCS;
				double vKL;
				CWeightedClassificationExampleList tFullImageExampleList;
				CWeightedClassificationExampleList tIEL;

				int MAX_IEL_Size = 64;
				int i_Repeat, i_IEL_Size;

				CSimpleTypeArray<double> List_avMD;
				List_avMD.Resize(MAX_IEL_Size+1); List_avMD.Fill(0.0);
				CSimpleTypeArray<double> List_avED;
				List_avED.Resize(MAX_IEL_Size+1); List_avED.Fill(0.0);
				CSimpleTypeArray<double> List_avCS;
				List_avCS.Resize(MAX_IEL_Size+1); List_avCS.Fill(0.0);
				CSimpleTypeArray<double> List_avKL;
				List_avKL.Resize(MAX_IEL_Size+1); List_avKL.Fill(0.0);

				for ( i_Class = 0; i_Class < FullDataSet.ClassAmount; ++i_Class )
				{
					const CClassInformation& tClassInfo = FullDataSet.List_ClassInfo.pElement[i_Class];
					const CSourceFeatureCountDataSet* pSrcFCDS = FullDataSet.GetPtrFCDS(i_Class);

					tNBM.Clear();
					pSrcFCDS->MakeSingleClassImageExampleList(tClassInfo.In_FCDS_Label, tFullImageExampleList, true, -1, -1, 0);
					tNBM.InitImageModel(pSrcFCDS, tClassInfo.In_FCDS_Label, tFullImageExampleList, -1, -1, 0);
					tNBM.vecF_P_f_given_c_D = tNBM.vecF_P_f_given_c_V;

					for ( i_IEL_Size = 1; i_IEL_Size <= MAX_IEL_Size; i_IEL_Size += i_IEL_Size )
					{
						vMD = vED = vCS = vKL = 0.0;
						for ( i_Repeat = 0; i_Repeat < RepeatAmount_NB; ++i_Repeat )
						{
							tIEL.myInit(tFullImageExampleList, (int)i_IEL_Size);
							tNBM.InitImageModel(pSrcFCDS, tClassInfo.In_FCDS_Label, tIEL, -1, -1, 0);
							vMD += tt = CVectorMath::ManhattanDistance(tNBM.vecF_P_f_given_c_D, tNBM.vecF_P_f_given_c_V);
							vED += tt = CVectorMath::EulerDistance(tNBM.vecF_P_f_given_c_D, tNBM.vecF_P_f_given_c_V);
							vCS += tt = CVectorMath::CosineSimilarity(tNBM.vecF_P_f_given_c_D, tNBM.vecF_P_f_given_c_V);
							vKL += tt = CVectorMath::KL_Divergence(tNBM.vecF_P_f_given_c_D, tNBM.vecF_P_f_given_c_V);
						}
						vMD /= RepeatAmount_NB; List_avMD.pElement[i_IEL_Size] += vMD / FullDataSet.ClassAmount;
						vED /= RepeatAmount_NB; List_avED.pElement[i_IEL_Size] += vED / FullDataSet.ClassAmount;
						vCS /= RepeatAmount_NB; List_avCS.pElement[i_IEL_Size] += vCS / FullDataSet.ClassAmount;
						vKL /= RepeatAmount_NB; List_avKL.pElement[i_IEL_Size] += vKL / FullDataSet.ClassAmount;
					}
					sprintf_s(strTemp, "Trained Naive Bayes Image Model [%03d/%d %s]...",
						i_Class, FullDataSet.ClassAmount, tClassInfo.strName.c_str());
					CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, false);
				}
				sprintf_s(strTemp, "#.Img\tV.MD\tV.ED\tV.CS\tV.KL");
				CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, true);
				for ( i_IEL_Size = 1; i_IEL_Size <= MAX_IEL_Size; i_IEL_Size += i_IEL_Size )
				{
					sprintf_s(strTemp, "%d\t%.3lf\t%.3lf\t%.3lf\t%.3lf",
						i_IEL_Size,
						List_avMD.pElement[i_IEL_Size],
						List_avED.pElement[i_IEL_Size],
						List_avCS.pElement[i_IEL_Size],
						List_avKL.pElement[i_IEL_Size]);
					CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, true);
				}
				sprintf_s(strTemp, "Finished Training Naive Bayes Image Model [%d];\n", FullDataSet.ClassAmount);
				CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, true);
				CExternalTools::ConsoleTools::OutputTextToStream(outFile_GlobalLog, strTemp, true);
			} // (op_TrainNBM & 2)

			if (op_ClassificationTask & 1)
			{
				int MaxExampleAmount_Train = 32;
				int MaxExampleAmount_Test = 50;

				int i_EA_Train;
				int i_Repeat;
				int i_Task;
				//int MinWI, MaxWI;
				//MinWI = -1; MaxWI = -1;

				int K, W;
				double ThPWC;
				double Lambda;

				K = DefaultK; W = DefaultW; ThPWC = DefaultThresholdPWC;

				CTaskSet_TAIC TaskSet;
				TaskSet.myInit(&FullDataSet, EnvVar.strFN_Task);

				for ( i_Task = 0; i_Task < TaskSet.TaskAmount; ++i_Task )
				{
					const CTask_TAIC& tTask = TaskSet.List_Task.pElement[i_Task];
					CSourceFeatureCountDataSet ImageFCDS_Train;
					CSourceFeatureCountDataSet ImageFCDS_Test;
					CSimpleTypeArray<CSVMLightHelper::CModel> List_SVM;
					CSimpleTypeArray<CSVMLightHelper::CModel> List_SVM_Search;
					CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC> List_NBM;
					CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC> List_NBM_Text;
					CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC> List_NBM_Search;

					List_SVM.Resize(tTask.ClassAmount);

					tTask.MakeClassificationDataSet(
						ImageFCDS_Train, 0,
						ImageFCDS_Test, 0,
						0, 0, K);
					tTask.TrainTextModel(List_NBM_Search, K, 1, 0.0);
					tTask.TrainImageModel(List_NBM_Search, ImageFCDS_Train);
					tTask.TrainImageSVM(List_SVM_Search, ImageFCDS_Train);

					tTask.MakeClassificationDataSet(
						ImageFCDS_Train, 0,
						ImageFCDS_Test, 0,
						-1, -1, 0);
					tTask.TrainTextModel(List_NBM_Text, K, W, ThPWC);
					tTask.TrainImageModel(List_NBM_Text, ImageFCDS_Train);
					List_NBM = List_NBM_Text;

					CSimpleStatistics Acc;
					double tAcc, mAcc, vAcc;

					sprintf_s(strTemp, "%d", i_Task);
					CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, false);

					int i_Method, i_RepeatAmount;
					for ( i_Method = 0; i_Method < 7; ++i_Method )
					{
						Acc.Clear();
						i_RepeatAmount = (i_Method<4 ? RepeatAmount_NB : RepeatAmount_SVM);
						for ( i_Repeat = 0; i_Repeat < i_RepeatAmount; ++i_Repeat )
						{
							bool fTrainImageNBM = false;
							bool fTrainImageSVM = false;
							bool fTestNBM = false;

							if (i_Method == 0) // Text Model
							{
								i_EA_Train = 0;
								List_NBM = List_NBM_Text;
								Lambda = 0.0;
								fTrainImageNBM = false;
								fTrainImageSVM = false;
								fTestNBM = true;
							}
							else if (i_Method == 1) // Search & NBM
							{
								i_EA_Train = 0;
								List_NBM = List_NBM_Search;
								Lambda = 0.0;
								fTrainImageNBM = false;
								fTrainImageSVM = false;
								fTestNBM = true;
							}
							else if (i_Method == 2) // Image.4 & NBM
							{
								i_EA_Train = 4;
								Lambda = MAXIMUM_DOUBLE_NUM_V;
								fTrainImageNBM = true;
								fTrainImageSVM = false;
								fTestNBM = true;
							}
							else if (i_Method == 3) // Image.32 & NBM
							{
								i_EA_Train = 32;
								Lambda = MAXIMUM_DOUBLE_NUM_V;
								fTrainImageNBM = true;
								fTrainImageSVM = false;
								fTestNBM = true;
							}
							else if (i_Method == 4) // Search & SVM
							{
								i_EA_Train = 0;
								List_SVM = List_SVM_Search;
								fTrainImageNBM = false;
								fTrainImageSVM = false;
								fTestNBM = false;
							}
							else if (i_Method == 5) // Image.4 & SVM
							{
								i_EA_Train = 4;
								fTrainImageNBM = false;
								fTrainImageSVM = true;
								fTestNBM = false;
							}
							else if (i_Method == 6) // Image.32 & SVM
							{
								i_EA_Train = 32;
								fTrainImageNBM = false;
								fTrainImageSVM = true;
								fTestNBM = false;
							}
							else
								;

							tTask.MakeClassificationDataSet(
								ImageFCDS_Train, i_EA_Train,
								ImageFCDS_Test, MaxExampleAmount_Test,
								-1, -1, 0);
							if (fTrainImageNBM)
								tTask.TrainImageModel(List_NBM, ImageFCDS_Train);
							if (fTrainImageSVM)
								tTask.TrainImageSVM(List_SVM, ImageFCDS_Train);
							if (fTestNBM)
							{
								tTask.TrainMixedModel(List_NBM, Lambda);
								tTask.Test(List_NBM, ImageFCDS_Test, tAcc);
							}
							else
								tTask.Test(List_SVM, ImageFCDS_Test, tAcc);
							Acc.NewInstance(tAcc);
						}
						Acc.Analyse(mAcc, vAcc);
						sprintf_s(strTemp, "\t%04.1lf  %02d", (1.0-mAcc)*100.0, (int)(vAcc*100.0+0.5));
						CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, false);
					} // i_Method
					CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, "", true);
					sprintf_s(strTemp, "Tested Task [%d/%d]...", i_Task, TaskSet.TaskAmount);
					CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, false);
				} // i_Task
				sprintf_s(strTemp, "Finished Testing Tasks [%d] Between Six Methods;\n", TaskSet.TaskAmount);
				CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, true);
				CExternalTools::ConsoleTools::OutputTextToStream(outFile_GlobalLog, strTemp, true);
			} // (op_ClassificationTask & 1)

			if (op_ClassificationTask & 2)
			{
				int LambdaAmount = 11;
				double StepLambda = 3.0;
				double BaseLambda = pow(StepLambda, -5.0);

				int i_EA_Train;
				int i_Task;
				int i_Lambda;
				int i_Repeat;

				int K, W;
				double ThPWC;
				double Lambda;

				K = DefaultK; W = DefaultW; ThPWC = DefaultThresholdPWC;

				CTaskSet_TAIC TaskSet;
				TaskSet.myInit(&FullDataSet, EnvVar.strFN_Task);

				CSimpleTypeArray<CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC>> matTask_NBM;
				matTask_NBM.Resize(TaskSet.TaskAmount);
				for ( i_Task = 0; i_Task < TaskSet.TaskAmount; ++i_Task )
				{
					const CTask_TAIC& tTask = TaskSet.List_Task.pElement[i_Task];
					CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC>& List_NBM = matTask_NBM.pElement[i_Task];
					tTask.TrainTextModel(List_NBM, K, W, ThPWC);
					sprintf_s(strTemp, "Trained Text Model [%d/%d]...",
						i_Task, TaskSet.TaskAmount);
					CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, false);
				} // i_Task
				sprintf_s(strTemp, "Finished Training Text Model [%d];",
					TaskSet.TaskAmount);
				CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, true);

				sprintf_s(strTemp, "Lambda");
				CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, false);
				for ( i_Lambda = 0; i_Lambda < LambdaAmount; ++i_Lambda )
				{
					Lambda = BaseLambda * pow(StepLambda, i_Lambda);
					sprintf_s(strTemp, "\t%+.0lf", log(Lambda)/log(StepLambda));
					CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, false);
				} // i_Lambda
				CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, "", true);

				for ( i_EA_Train = 1; i_EA_Train <= MaxExampleAmount_Train; i_EA_Train += i_EA_Train )
				{
					CSimpleTypeArray<CSimpleStatistics> List_Acc;
					double tAcc, mAcc, vAcc;

					List_Acc.Resize(LambdaAmount);
					for ( i_Lambda = 0; i_Lambda < LambdaAmount; ++i_Lambda )
						List_Acc.pElement[i_Lambda].Clear();
					for ( i_Task = 0; i_Task < TaskSet.TaskAmount; ++i_Task )
					{
						const CTask_TAIC& tTask = TaskSet.List_Task.pElement[i_Task];
						CSourceFeatureCountDataSet ImageFCDS_Train;
						CSourceFeatureCountDataSet ImageFCDS_Test;
						CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC>& List_NBM = matTask_NBM.pElement[i_Task];

						for ( i_Lambda = 0; i_Lambda < LambdaAmount; ++i_Lambda )
						{
							Lambda = BaseLambda * pow(StepLambda, i_Lambda);
							CSimpleStatistics& iAcc = List_Acc.pElement[i_Lambda];
							for ( i_Repeat = 0; i_Repeat < RepeatAmount_NB; ++i_Repeat )
							{
								tTask.MakeClassificationDataSet(
									ImageFCDS_Train, i_EA_Train,
									ImageFCDS_Test, MaxExampleAmount_Test,
									-1, -1, 0);
								tTask.TrainImageModel(List_NBM, ImageFCDS_Train);
								tTask.TrainMixedModel(List_NBM, Lambda);
								tTask.Test(List_NBM, ImageFCDS_Test, tAcc);
								iAcc.NewInstance(tAcc);
							}

							sprintf_s(strTemp, "Tested Lambda [%d/%d] Task [%d/%d] IEA [%d]...",
								i_Lambda, LambdaAmount, i_Task, TaskSet.TaskAmount, i_EA_Train);
							CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, false);
						} // i_Lambda
					} // i_Task

					sprintf_s(strTemp, "%d", i_EA_Train);
					CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, false);
					for ( i_Lambda = 0; i_Lambda < LambdaAmount; ++i_Lambda )
					{
						CSimpleStatistics& iAcc = List_Acc.pElement[i_Lambda];
						iAcc.Analyse(mAcc, vAcc);
						sprintf_s(strTemp, "\t%.3lf", 1.0-mAcc);
						CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, false);
					} // i_Lambda
					CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, "", true);
				} // i_EA_Train

				sprintf_s(strTemp, "Finished Testing <IEA:Lambda> Tasks;");
				CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, true);
				CExternalTools::ConsoleTools::OutputTextToStream(outFile_GlobalLog, strTemp, true);
			} // (op_ClassificationTask & 2)

			if (op_ClassificationTask & 4)
			{
				int MaxExampleAmount_Train = 32;
				int MaxExampleAmount_Test = 50;

				int i_EA_Train;
				int i_Repeat;
				int i_Task;
				int MinWI, MaxWI, KWI;
				MinWI = -1; MaxWI = -1; KWI = 0;

				int K, W;
				double ThPWC;
				double Lambda;

				K = DefaultK; W = DefaultW; ThPWC = DefaultThresholdPWC;

				CTaskSet_TAIC TaskSet;
				TaskSet.myInit(&FullDataSet, EnvVar.strFN_Task);

				CSimpleTypeArray<CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC>> List_List_NBM_Text;
				List_List_NBM_Text.Resize(TaskSet.TaskAmount);
				for ( i_Task = 0; i_Task < TaskSet.TaskAmount; ++i_Task )
				{
					const CTask_TAIC& tTask = TaskSet.List_Task.pElement[i_Task];
					CSourceFeatureCountDataSet ImageFCDS_Train;
					CSourceFeatureCountDataSet ImageFCDS_Test;
					CSimpleTypeArray<CSVMLightHelper::CModel> List_SVM;
					CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC>& tList_NBM_Text = List_List_NBM_Text.pElement[i_Task];
					List_SVM.Resize(tTask.ClassAmount);
					tTask.MakeClassificationDataSet(
						ImageFCDS_Train, 0,
						ImageFCDS_Test, 0,
						-1, -1, 0);
					tTask.TrainTextModel(tList_NBM_Text, K, W, ThPWC);
					tTask.TrainImageModel(tList_NBM_Text, ImageFCDS_Train);
				}

				for ( i_EA_Train = 1; i_EA_Train <= MaxExampleAmount_Train; i_EA_Train += i_EA_Train )
				{
					sprintf_s(strTemp, "%d", i_EA_Train);
					CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, false);
					double tAcc, mAcc, vAcc;
					int i_Method, i_RepeatAmount;

					int AmountMethod = 6;
					double u = 20.0;

					for ( i_Method = 0; i_Method < AmountMethod; ++i_Method )
					{
						CSimpleStatistics OT_Acc;
						OT_Acc.Clear();
						for ( i_Task = 0; i_Task < TaskSet.TaskAmount; ++i_Task )
						{
							const CTask_TAIC& tTask = TaskSet.List_Task.pElement[i_Task];
							CSourceFeatureCountDataSet ImageFCDS_Train;
							CSourceFeatureCountDataSet ImageFCDS_Test;
							CSimpleTypeArray<CSVMLightHelper::CModel> List_SVM;
							CSimpleTypeArray<CSingleClassNaiveBayesModel_TAIC> List_NBM;

							List_NBM = List_List_NBM_Text.pElement[i_Task];

							CSimpleStatistics Acc;
							Acc.Clear();
							i_RepeatAmount = (i_Method<4 ? RepeatAmount_NB : RepeatAmount_SVM);

							for ( i_Repeat = 0; i_Repeat < i_RepeatAmount; ++i_Repeat )
							{
								bool fTrainImageNBM = false;
								bool fTrainImageSVM = false;
								bool fTestNBM = false;

								if (i_Method == 0) // TAIC Model, various lambda
								{
									MinWI = -1; MaxWI = -1; KWI = 0;

									//using u
									//Lambda = DefaultLambda;
									Lambda = 1.0 * i_EA_Train / (u + i_EA_Train);

									fTrainImageNBM = true;
									fTrainImageSVM = false;
									fTestNBM = true;
								}
								if (i_Method == 1) // TAIC Model, fix lambda
								{
									MinWI = -1; MaxWI = -1; KWI = 0;
									Lambda = DefaultLambda;
									fTrainImageNBM = true;
									fTrainImageSVM = false;
									fTestNBM = true;
								}
								else if (i_Method == 2) // Image & NBM
								{
									MinWI = -1; MaxWI = -1; KWI = 0;
									Lambda = MAXIMUM_DOUBLE_NUM_V;
									fTrainImageNBM = true;
									fTrainImageSVM = false;
									fTestNBM = true;
								}
								else if (i_Method == 3) // Image+Search & NBM
								{
									MinWI = -1; MaxWI = 0; KWI = K;
									Lambda = MAXIMUM_DOUBLE_NUM_V;
									fTrainImageNBM = true;
									fTrainImageSVM = false;
									fTestNBM = true;
								}
								else if (i_Method == 4) // Image & SVM
								{
									MinWI = -1; MaxWI = -1; KWI = 0;
									fTrainImageNBM = false;
									fTrainImageSVM = true;
									fTestNBM = false;
								}
								else if (i_Method == 5) // Image+Search & SVM
								{
									MinWI = -1; MaxWI = 0; KWI = K;
									fTrainImageNBM = false;
									fTrainImageSVM = true;
									fTestNBM = false;
								}
								else
									;

								tTask.MakeClassificationDataSet(
									ImageFCDS_Train, i_EA_Train,
									ImageFCDS_Test, MaxExampleAmount_Test,
									MinWI, MaxWI, KWI);
								if (fTrainImageNBM)
									tTask.TrainImageModel(List_NBM, ImageFCDS_Train);
								if (fTrainImageSVM)
									tTask.TrainImageSVM(List_SVM, ImageFCDS_Train);
								if (fTestNBM)
								{
									tTask.TrainMixedModel(List_NBM, Lambda);
									tTask.Test(List_NBM, ImageFCDS_Test, tAcc);
								}
								else
									tTask.Test(List_SVM, ImageFCDS_Test, tAcc);
								Acc.NewInstance(tAcc);
							} // i_Repeat
							Acc.Analyse(mAcc, vAcc);
							OT_Acc.NewInstance(mAcc);
							sprintf_s(strTemp, "Tested Task [%d/%d] Method [%d/%d] EA_Train [%d/%d]...",
								i_Task, TaskSet.TaskAmount, i_Method, AmountMethod, i_EA_Train, MaxExampleAmount_Train);
							CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, false);
						} // i_Task
						OT_Acc.Analyse(mAcc, vAcc);
						sprintf_s(strTemp, "\t%04.1lf", (1.0-mAcc)*100.0);
						CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, strTemp, false);
					} // i_Method
					CExternalTools::ConsoleTools::OutputTextToStream(outFile_ShortLog, "", true);
				} // i_EA_Train
				sprintf_s(strTemp, "Finished Testing Tasks [%d] Between Five Methods Over EA_Train;\n", TaskSet.TaskAmount);
				CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, true);
				CExternalTools::ConsoleTools::OutputTextToStream(outFile_GlobalLog, strTemp, true);
			} // (op_ClassificationTask & 4)
		} // Main Code

		outFile_ShortLog.close();
		outFile_ShortLog.clear();
		CExternalTools::ConsoleTools::MakeCurrentLine("", true);
		CExternalTools::ConsoleTools::OutputTextToStream(outFile_GlobalLog, "", true);
		outFile_GlobalLog.close();
		outFile_GlobalLog.clear();
	}

	CImageEx::Release();
	return 0;
}

